{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `partition_conversions`\n",
    "\n",
    "{func}`tvm.relay.quantize._partition_conversions.partition_conversions` 将模块划分为输入量化、核心量化推理和输出反量化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import set_env"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tvm\n",
    "from tvm.runtime.vm import VirtualMachine\n",
    "from tvm import relay\n",
    "from torch import nn\n",
    "import torch\n",
    "\n",
    "class Model(nn.Module):\n",
    "    def __init__(self, *args, **kwargs) -> None:\n",
    "        super().__init__(*args, **kwargs)\n",
    "        self.conv = nn.Conv2d(3, 16, 3, 1, 1, bias=True)\n",
    "        self.bn = nn.BatchNorm2d(16)\n",
    "        self.relu = nn.ReLU()\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.conv(x)\n",
    "        x = self.bn(x)\n",
    "        x = self.relu(x)\n",
    "        return x\n",
    "\n",
    "def create_model(ishape = (1, 3, 4, 4)):\n",
    "    pt_model = Model().eval().float()\n",
    "    input_shapes = [(\"data\", ishape)]\n",
    "    # script_module = torch.jit.script(pt_model)\n",
    "    # mod, params = relay.frontend.from_pytorch(script_module, input_shapes)\n",
    "    idata = torch.rand(ishape).type(torch.float32)\n",
    "    traced_model = torch.jit.trace(pt_model, idata)\n",
    "    # traced_model 翻译为 TVM 前端模型\n",
    "    mod, params = relay.frontend.from_pytorch(traced_model, input_shapes, \n",
    "                                              use_parser_friendly_name=True)\n",
    "    return mod, params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "修改前量化配置：\n",
      "qconfig(nbit_input=8, nbit_weight=8, nbit_activation=32, calibrate_mode=global_scale, global_scale=8, weight_scale=power2, skip_conv_layers==(nullptr), skip_dense_layer==1, do_simulation==0, round_for_shift==1, debug_enabled_ops==(nullptr), rounding==UPWARD, partition_conversions==disabled)\n",
      "当前量化配置：\n",
      "qconfig(nbit_input=8, nbit_weight=8, nbit_activation=32, calibrate_mode=global_scale, global_scale=8, weight_scale=power2, skip_conv_layers==[], skip_dense_layer==1, do_simulation==1, round_for_shift==1, debug_enabled_ops==(nullptr), rounding==UPWARD, partition_conversions==disabled)\n",
      "\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "module 'numpy' has no attribute 'math'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mAttributeError\u001b[39m                            Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 9\u001b[39m\n\u001b[32m      4\u001b[39m     \u001b[38;5;28;01mwith\u001b[39;00m relay.quantize.qconfig(\n\u001b[32m      5\u001b[39m         skip_conv_layers=[],\n\u001b[32m      6\u001b[39m         do_simulation=\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m      7\u001b[39m     ):\n\u001b[32m      8\u001b[39m         \u001b[38;5;28mprint\u001b[39m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33m当前量化配置：\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00mrelay.quantize.current_qconfig()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m\"\u001b[39m)\n\u001b[32m----> \u001b[39m\u001b[32m9\u001b[39m         qmod = \u001b[43mrelay\u001b[49m\u001b[43m.\u001b[49m\u001b[43mquantize\u001b[49m\u001b[43m.\u001b[49m\u001b[43mquantize\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmod\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m     10\u001b[39m \u001b[38;5;28mprint\u001b[39m(qmod)\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/relay/quantize/quantize.py:370\u001b[39m, in \u001b[36mquantize\u001b[39m\u001b[34m(mod, params, dataset)\u001b[39m\n\u001b[32m    366\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m tvm.transform.PassContext(\n\u001b[32m    367\u001b[39m     opt_level=\u001b[32m3\u001b[39m, required_pass=[\u001b[33m\"\u001b[39m\u001b[33mQuantizeAnnotate\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mQuantizeCalibrate\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mQuantizeRealize\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m    368\u001b[39m ):\n\u001b[32m    369\u001b[39m     \u001b[38;5;28;01mwith\u001b[39;00m quantize_context():\n\u001b[32m--> \u001b[39m\u001b[32m370\u001b[39m         mod = \u001b[43mquantize_seq\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmod\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m    372\u001b[39m q_cfg = current_qconfig()\n\u001b[32m    373\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m q_cfg.partition_conversions \u001b[38;5;129;01min\u001b[39;00m [\u001b[33m\"\u001b[39m\u001b[33mdisabled\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33menabled\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mfully_integral\u001b[39m\u001b[33m\"\u001b[39m]\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/ir/transform.py:238\u001b[39m, in \u001b[36mPass.__call__\u001b[39m\u001b[34m(self, mod)\u001b[39m\n\u001b[32m    224\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, mod):\n\u001b[32m    225\u001b[39m \u001b[38;5;250m    \u001b[39m\u001b[33;03m\"\"\"Execute the pass. Note that for sequential pass, the dependency among\u001b[39;00m\n\u001b[32m    226\u001b[39m \u001b[33;03m    different passes will be resolved in the backend.\u001b[39;00m\n\u001b[32m    227\u001b[39m \n\u001b[32m   (...)\u001b[39m\u001b[32m    236\u001b[39m \u001b[33;03m        The updated module after applying this pass.\u001b[39;00m\n\u001b[32m    237\u001b[39m \u001b[33;03m    \"\"\"\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m238\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ffi_transform_api\u001b[49m\u001b[43m.\u001b[49m\u001b[43mRunPass\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmod\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/_ffi/_ctypes/packed_func.py:245\u001b[39m, in \u001b[36mPackedFuncBase.__call__\u001b[39m\u001b[34m(self, *args)\u001b[39m\n\u001b[32m    233\u001b[39m ret_tcode = ctypes.c_int()\n\u001b[32m    234\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[32m    235\u001b[39m     _LIB.TVMFuncCall(\n\u001b[32m    236\u001b[39m         \u001b[38;5;28mself\u001b[39m.handle,\n\u001b[32m   (...)\u001b[39m\u001b[32m    243\u001b[39m     != \u001b[32m0\u001b[39m\n\u001b[32m    244\u001b[39m ):\n\u001b[32m--> \u001b[39m\u001b[32m245\u001b[39m     \u001b[43mraise_last_ffi_error\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m    246\u001b[39m _ = temp_args\n\u001b[32m    247\u001b[39m _ = args\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/_ffi/base.py:481\u001b[39m, in \u001b[36mraise_last_ffi_error\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    475\u001b[39m \u001b[38;5;66;03m# The exception PyObject may contain a large amount of state,\u001b[39;00m\n\u001b[32m    476\u001b[39m \u001b[38;5;66;03m# including all stack frames that may be inspected in a later\u001b[39;00m\n\u001b[32m    477\u001b[39m \u001b[38;5;66;03m# PDB post-mortem.  Therefore, we must make sure to remove the\u001b[39;00m\n\u001b[32m    478\u001b[39m \u001b[38;5;66;03m# underlying PyObject* from the C++ side after we retrieve it.\u001b[39;00m\n\u001b[32m    479\u001b[39m _LIB.TVMDropLastPythonError()\n\u001b[32m--> \u001b[39m\u001b[32m481\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m py_err\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/relay/quantize/_calibrate.py:236\u001b[39m, in \u001b[36mcalibrate.<locals>.wrapped_func\u001b[39m\u001b[34m(mod, _)\u001b[39m\n\u001b[32m    233\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m    234\u001b[39m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mUnknown weight scale mode \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcfg.weight_scale\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m\"\u001b[39m)\n\u001b[32m--> \u001b[39m\u001b[32m236\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_set_params\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmod\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43minput_scale_func\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mweight_scale_func\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/relay/quantize/_calibrate.py:168\u001b[39m, in \u001b[36m_set_params\u001b[39m\u001b[34m(mod, input_scale_func, weight_scale_func)\u001b[39m\n\u001b[32m    165\u001b[39m         const_params[nclip_max] = _make_const((valid_range - \u001b[32m1\u001b[39m))\n\u001b[32m    167\u001b[39m main_func = mod[\u001b[33m\"\u001b[39m\u001b[33mmain\u001b[39m\u001b[33m\"\u001b[39m]\n\u001b[32m--> \u001b[39m\u001b[32m168\u001b[39m \u001b[43m_analysis\u001b[49m\u001b[43m.\u001b[49m\u001b[43mpost_order_visit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmain_func\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvisit_func\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m    169\u001b[39m main_func = _expr.bind(main_func, const_params)\n\u001b[32m    170\u001b[39m func_dict = {}\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/relay/analysis/analysis.py:44\u001b[39m, in \u001b[36mpost_order_visit\u001b[39m\u001b[34m(expr, fvisit)\u001b[39m\n\u001b[32m     31\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mpost_order_visit\u001b[39m(expr, fvisit):\n\u001b[32m     32\u001b[39m \u001b[38;5;250m    \u001b[39m\u001b[33;03m\"\"\"Recursively visit the ir in post DFS order node,\u001b[39;00m\n\u001b[32m     33\u001b[39m \u001b[33;03m    apply fvisit. Each node is guaranteed to be visited\u001b[39;00m\n\u001b[32m     34\u001b[39m \u001b[33;03m    only once.\u001b[39;00m\n\u001b[32m   (...)\u001b[39m\u001b[32m     42\u001b[39m \u001b[33;03m        The visitor function to be applied.\u001b[39;00m\n\u001b[32m     43\u001b[39m \u001b[33;03m    \"\"\"\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m44\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_ffi_api\u001b[49m\u001b[43m.\u001b[49m\u001b[43mpost_order_visit\u001b[49m\u001b[43m(\u001b[49m\u001b[43mexpr\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfvisit\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:427\u001b[39m, in \u001b[36moperator()\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    425\u001b[39m \n\u001b[32m    426\u001b[39m TVM_REGISTER_GLOBAL(\"relay.analysis.post_order_visit\").set_body_typed([](Expr expr, PackedFunc f) {\n\u001b[32m--> \u001b[39m\u001b[32m427\u001b[39m   PostOrderVisit(expr, [f](const Expr& n) { f(n); });\n\u001b[32m    428\u001b[39m });\n\u001b[32m    429\u001b[39m \n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:423\u001b[39m, in \u001b[36mtvm::relay::PostOrderVisit(tvm::RelayExpr const&, std::function<void (tvm::RelayExpr const&)>)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    421\u001b[39m \n\u001b[32m    422\u001b[39m void PostOrderVisit(const Expr& e, std::function<void(const Expr&)> fvisit) {\n\u001b[32m--> \u001b[39m\u001b[32m423\u001b[39m   ExprApplyVisit(fvisit).VisitExpr(e);\n\u001b[32m    424\u001b[39m }\n\u001b[32m    425\u001b[39m \n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:413\u001b[39m, in \u001b[36mtvm::relay::ExprApplyVisit::VisitExpr(tvm::RelayExpr const&)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    411\u001b[39m   if (visited_.count(e.get()) != 0) return;\n\u001b[32m    412\u001b[39m   visited_.insert(e.get());\n\u001b[32m--> \u001b[39m\u001b[32m413\u001b[39m   ExprVisitor::VisitExpr(e);\n\u001b[32m    414\u001b[39m   f_(e);\n\u001b[32m    415\u001b[39m }\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:295\u001b[39m, in \u001b[36mtvm::relay::ExprVisitor::VisitExpr(tvm::RelayExpr const&)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    293\u001b[39m } else {\n\u001b[32m    294\u001b[39m   using TParent = ExprFunctor<void(const Expr&)>;\n\u001b[32m--> \u001b[39m\u001b[32m295\u001b[39m   TParent::VisitExpr(expr);\n\u001b[32m    296\u001b[39m   visit_counter_.insert({expr.get(), 1});\n\u001b[32m    297\u001b[39m }\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:413\u001b[39m, in \u001b[36mtvm::relay::ExprApplyVisit::VisitExpr(tvm::RelayExpr const&)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    411\u001b[39m   if (visited_.count(e.get()) != 0) return;\n\u001b[32m    412\u001b[39m   visited_.insert(e.get());\n\u001b[32m--> \u001b[39m\u001b[32m413\u001b[39m   ExprVisitor::VisitExpr(e);\n\u001b[32m    414\u001b[39m   f_(e);\n\u001b[32m    415\u001b[39m }\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:295\u001b[39m, in \u001b[36mtvm::relay::ExprVisitor::VisitExpr(tvm::RelayExpr const&)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    293\u001b[39m } else {\n\u001b[32m    294\u001b[39m   using TParent = ExprFunctor<void(const Expr&)>;\n\u001b[32m--> \u001b[39m\u001b[32m295\u001b[39m   TParent::VisitExpr(expr);\n\u001b[32m    296\u001b[39m   visit_counter_.insert({expr.get(), 1});\n\u001b[32m    297\u001b[39m }\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:336\u001b[39m, in \u001b[36mtvm::relay::ExprVisitor::VisitExpr_(tvm::relay::CallNode const*)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    334\u001b[39m \n\u001b[32m    335\u001b[39m   for (auto arg : op->args) {\n\u001b[32m--> \u001b[39m\u001b[32m336\u001b[39m     this->VisitExpr(arg);\n\u001b[32m    337\u001b[39m   }\n\u001b[32m    338\u001b[39m }\n",
      "    \u001b[31m[... skipping similar frames: tvm::relay::ExprApplyVisit::VisitExpr(tvm::RelayExpr const&) at line 413 (1 times), tvm::relay::ExprVisitor::VisitExpr(tvm::RelayExpr const&) at line 295 (1 times)]\u001b[39m\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:336\u001b[39m, in \u001b[36mtvm::relay::ExprVisitor::VisitExpr_(tvm::relay::CallNode const*)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    334\u001b[39m \n\u001b[32m    335\u001b[39m   for (auto arg : op->args) {\n\u001b[32m--> \u001b[39m\u001b[32m336\u001b[39m     this->VisitExpr(arg);\n\u001b[32m    337\u001b[39m   }\n\u001b[32m    338\u001b[39m }\n",
      "    \u001b[31m[... skipping similar frames: tvm::relay::ExprApplyVisit::VisitExpr(tvm::RelayExpr const&) at line 413 (4 times), tvm::relay::ExprVisitor::VisitExpr(tvm::RelayExpr const&) at line 295 (4 times), tvm::relay::ExprVisitor::VisitExpr_(tvm::relay::CallNode const*) at line 336 (4 times)]\u001b[39m\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:413\u001b[39m, in \u001b[36mtvm::relay::ExprApplyVisit::VisitExpr(tvm::RelayExpr const&)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    411\u001b[39m   if (visited_.count(e.get()) != 0) return;\n\u001b[32m    412\u001b[39m   visited_.insert(e.get());\n\u001b[32m--> \u001b[39m\u001b[32m413\u001b[39m   ExprVisitor::VisitExpr(e);\n\u001b[32m    414\u001b[39m   f_(e);\n\u001b[32m    415\u001b[39m }\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:295\u001b[39m, in \u001b[36mtvm::relay::ExprVisitor::VisitExpr(tvm::RelayExpr const&)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    293\u001b[39m } else {\n\u001b[32m    294\u001b[39m   using TParent = ExprFunctor<void(const Expr&)>;\n\u001b[32m--> \u001b[39m\u001b[32m295\u001b[39m   TParent::VisitExpr(expr);\n\u001b[32m    296\u001b[39m   visit_counter_.insert({expr.get(), 1});\n\u001b[32m    297\u001b[39m }\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/src/relay/ir/expr_functor.cc:336\u001b[39m, in \u001b[36mtvm::relay::ExprVisitor::VisitExpr_(tvm::relay::CallNode const*)\u001b[39m\u001b[34m()\u001b[39m\n\u001b[32m    334\u001b[39m \n\u001b[32m    335\u001b[39m   for (auto arg : op->args) {\n\u001b[32m--> \u001b[39m\u001b[32m336\u001b[39m     this->VisitExpr(arg);\n\u001b[32m    337\u001b[39m   }\n\u001b[32m    338\u001b[39m }\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/relay/quantize/_calibrate.py:155\u001b[39m, in \u001b[36m_set_params.<locals>.visit_func\u001b[39m\u001b[34m(expr)\u001b[39m\n\u001b[32m    153\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m kind == quantize.QAnnotateKind.WEIGHT:\n\u001b[32m    154\u001b[39m     \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(expr.args[\u001b[32m0\u001b[39m], _expr.Constant)\n\u001b[32m--> \u001b[39m\u001b[32m155\u001b[39m     scale = \u001b[43mweight_scale_func\u001b[49m\u001b[43m(\u001b[49m\u001b[43mexpr\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m    156\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m    157\u001b[39m     scale = input_scale_func(expr)\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/board/arria10/lxw/tasks/tvm-ai/python/tvm/relay/quantize/_calibrate.py:183\u001b[39m, in \u001b[36m_power2_scale\u001b[39m\u001b[34m(sq_call)\u001b[39m\n\u001b[32m    181\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(var, _expr.Constant)\n\u001b[32m    182\u001b[39m val = np.amax(np.abs(var.data.numpy()))\n\u001b[32m--> \u001b[39m\u001b[32m183\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[32m2\u001b[39m ** \u001b[43mnp\u001b[49m\u001b[43m.\u001b[49m\u001b[43mmath\u001b[49m.ceil(np.math.log(val, \u001b[32m2\u001b[39m)) \u001b[38;5;28;01mif\u001b[39;00m val > \u001b[32m0\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m \u001b[32m1.0\u001b[39m\n",
      "\u001b[36mFile \u001b[39m\u001b[32m/media/pc/data/lxw/envs/anaconda3a/envs/tvm-env/lib/python3.13/site-packages/numpy/__init__.py:414\u001b[39m, in \u001b[36m__getattr__\u001b[39m\u001b[34m(attr)\u001b[39m\n\u001b[32m    411\u001b[39m     \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mnumpy\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mchar\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mchar\u001b[39;00m\n\u001b[32m    412\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m char.chararray\n\u001b[32m--> \u001b[39m\u001b[32m414\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m(\u001b[33m\"\u001b[39m\u001b[33mmodule \u001b[39m\u001b[38;5;132;01m{!r}\u001b[39;00m\u001b[33m has no attribute \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m    415\u001b[39m                      \u001b[33m\"\u001b[39m\u001b[38;5;132;01m{!r}\u001b[39;00m\u001b[33m\"\u001b[39m.format(\u001b[34m__name__\u001b[39m, attr))\n",
      "\u001b[31mAttributeError\u001b[39m: module 'numpy' has no attribute 'math'"
     ]
    }
   ],
   "source": [
    "print(f\"修改前量化配置：\\n{relay.quantize.current_qconfig()}\")\n",
    "mod, params = create_model(ishape = (1, 3, 4, 4))\n",
    "with tvm.transform.PassContext(opt_level=3):\n",
    "    with relay.quantize.qconfig(\n",
    "        skip_conv_layers=[],\n",
    "        do_simulation=True\n",
    "    ):\n",
    "        print(f\"当前量化配置：\\n{relay.quantize.current_qconfig()}\\n\")\n",
    "        qmod = relay.quantize.quantize(mod, params)\n",
    "print(qmod)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "mod, params = create_model(ishape = (1, 3, 4, 4))\n",
    "with tvm.transform.PassContext(opt_level=3):\n",
    "    with relay.quantize.qconfig(\n",
    "        skip_conv_layers=[],\n",
    "        partition_conversions=\"enabled\",\n",
    "        do_simulation=False\n",
    "    ):\n",
    "        print(f\"当前量化配置：\\n{relay.quantize.current_qconfig()}\\n\")\n",
    "        qmod = relay.quantize.quantize(mod, params)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(qmod)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dev = tvm.cpu()\n",
    "data_np = np.random.uniform(low=-1, high=1, size=[1, 3, 4, 4]).astype(\"float32\")\n",
    "input_dict = {\"data\": data_np}\n",
    "\n",
    "with tvm.transform.PassContext(opt_level=3):\n",
    "    qvm_exec = relay.vm.compile(qmod, target=\"llvm\", params=params)\n",
    "qvm = VirtualMachine(qvm_exec, dev)\n",
    "qvm.set_input(\"main\", **input_dict)\n",
    "tvm_qres = qvm.run()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "tvm-env",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
